﻿#include "FTPs.h"

// FTP读取函数

size_t FTPs::readFunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
	size_t n;
	FILE* f = (FILE*)stream;
	if (ferror(f))
	{
		return CURL_READFUNC_ABORT;
	}

	n = fread(ptr, size, nmemb, f) * size;
	return n;
}

// FTP写入函数
size_t FTPs::writeData(void* buffer, size_t size, size_t nmemb, void* userp)
{
	FILE* fp = (FILE*)userp; // 将用户参数转换为文件指针
	if (ferror(fp))
	{
		return CURLE_WRITE_ERROR;
	}
	size_t written = fwrite(buffer, size, nmemb, fp); // 将缓冲区中的数据写入文件
	return written; // 返回写入的字节数
}

/******************************************************************************
*  Name         :   FTP::ftpUpload
*  Describe     :   FTP上传函数
*  remoteFtpPath：  需要上传的ftp服务端地址和文件名
*  localFilePath：  本地需要上传的文件完整路径
*  timeout      ：  上传超时时间 0：disable
*  return       ：  0:成功 -1：失败
******************************************************************************/
int FTPs::ftpUpload(const char* remoteFtpPath, const char* localFilePath, long timeout)
{
	CURL* curl = NULL;
	curl_global_init(CURL_GLOBAL_ALL); // 初始化libcurl库

	struct stat file_info;
	curl_off_t fsize;
	if (stat(localFilePath, &file_info))    /* 获得上传文件的大小 */
	{
		printf("FTP file could n't open '%s': %s.", localFilePath, strerror(errno));
		return -1;
	}
	fsize = (curl_off_t)file_info.st_size;

	FILE* fd;
	fd = fopen(localFilePath, "rb"); // 以二进制读模式打开本地文件
	if (fd == NULL)
	{
		printf("FTP fopen file failed.");
		return -1;
	}

	curl = curl_easy_init(); // 初始化一个CURL对象
	if (curl == NULL)
	{
		printf("FTP curl_easy_init create curl failed.");
		return -1;
	}

	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);               //使能上传功能
	curl_easy_setopt(curl, CURLOPT_URL, remoteFtpPath);        //设置特定目标

	curl_easy_setopt(curl, CURLOPT_USERNAME, "Administrator");
	curl_easy_setopt(curl, CURLOPT_PASSWORD, "20000331zjl");
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, FTPs::readFunc);   //使用curl提供的Read功能
	curl_easy_setopt(curl, CURLOPT_READDATA, fd);             //将参数fd传递给回调函数readfunc的第四个参数
	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);              //调试信息打印        
	curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, fsize);    /*设置要上传的文件的大小（可选） */

	if (timeout)
	{
		curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
	}

	CURLcode r = curl_easy_perform(curl); // 执行上传操作
	fclose(fd); // 关闭文件

	if (r != CURLE_OK)
	{
		printf("FTP upload event %s.", curl_easy_strerror(r));
		return -1;
	}


	if (curl)
	{
		curl_easy_cleanup(curl); // 清理CURL对象
	}

	curl_global_cleanup(); // 清理libcurl库

	return 0;
}

int FTPs::ftpDownload(const char* remoteFtpPath, const char* localFilePath, long timeout)
{
	CURL* curl; // 定义一个CURL类型的指针
	CURLcode res; // 定义一个CURLcode类型的变量，用于存储操作结果
	FILE* fp; // 定义一个文件指针
	// 替换为你要下载的FTP文件的URL
	// 替换为本地保存文件的路径和名称

	curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化libcurl库
	curl = curl_easy_init(); // 初始化CURL对象
	if (curl)
	{ // 如果CURL对象创建成功
		fp = fopen(localFilePath, "wb"); // 以二进制写模式打开本地文件
		if (!fp) { // 如果无法打开本地文件
			std::cout << "无法打开本地文件" << std::endl;
			curl_easy_cleanup(curl); // 清理CURL对象
			return 1; // 返回错误代码1
		}

		curl_easy_setopt(curl, CURLOPT_URL, remoteFtpPath); // 设置要下载的FTP文件的URL
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData); // 设置写入数据的回调函数
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); // 设置写入数据的回调函数的参数

		if (timeout)
		{
			curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
		}

		res = curl_easy_perform(curl); // 执行FTP文件下载操作
		if (res != CURLE_OK) { // 如果下载失败
			std::cout << "下载失败： " << curl_easy_strerror(res) << std::endl; // 输出错误信息
		}
		else { // 如果下载成功
			std::cout << "文件下载成功" << std::endl; // 输出成功信息
		}

		fclose(fp); // 关闭本地文件
		curl_easy_cleanup(curl); // 清理CURL对象
	}
	else
	{
		std::cout << "curl对象创建失败" << std::endl; // 输出成功信息
	}

	curl_global_cleanup(); // 清理libcurl库
	return 0; // 返回0表示程序正常结束
}